package com.jwsoft.manager.core.integration.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.engine.assistant.core.utils.SessionUtil;
import com.bifang.engine.cache.redis.RedisHelper;
import com.bifang.engine.data.core.util.PagerUtil;
import com.bifang.module.base.common.vo.dict.DictQueryVO;
import com.bifang.module.base.common.vo.dict.SelectVO;
import com.bifang.module.base.common.vo.excel.ExcelModelVO;
import com.bifang.module.base.common.vo.excel.ExcelParamVO;
import com.bifang.module.base.common.vo.excel.ExcelVO;
import com.bifang.module.base.core.helper.DictHelper;
import com.bifang.module.base.core.helper.ExcelCommonHelper;
import com.bifang.module.base.core.integration.DictIntegration;
import com.bifang.module.base.core.integration.ExcelIntegration;
import com.bifang.module.system.core.dao.model.SysApplication;
import com.bifang.module.system.core.dao.service.ExcelModelService;
import com.bifang.module.system.core.dao.service.ExcelParamService;
import com.bifang.module.system.core.dao.service.SysApplicationService;
import com.bifang.module.system.core.dao.service.SysDictService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.constant.EduCache;
import com.jwsoft.manager.common.enums.CardTypeEnum;
import com.jwsoft.manager.common.enums.JhSyncImportEnum;
import com.jwsoft.manager.common.enums.JhSyncTypeEnum;
import com.jwsoft.manager.common.vo.eduSyncJhDelete.EduSyncJhDeleteQueryVO;
import com.jwsoft.manager.common.vo.eduSyncJhEnroll.EduSyncJhEnrollKeyVO;
import com.jwsoft.manager.common.vo.eduSyncJhEnroll.EduSyncJhEnrollQueryVO;
import com.jwsoft.manager.common.vo.eduSyncJhEnroll.EduSyncJhEnrollVO;
import com.jwsoft.manager.core.dao.model.EduSyncJhApply;
import com.jwsoft.manager.core.dao.model.EduSyncJhApprove;
import com.jwsoft.manager.core.dao.model.EduSyncJhEnroll;
import com.jwsoft.manager.core.dao.model.EduSyncJhEnrollError;
import com.jwsoft.manager.core.dao.service.*;
import com.jwsoft.manager.core.integration.EduSyncJhEnrollIntegration;
import com.jwsoft.manager.core.integration.EduSyncJhImportBatchIntegration;
import com.jwsoft.manager.core.util.EduDesensitizeUtil;
import com.jwsoft.manager.core.util.EduHelper;
import com.jwsoft.manager.core.util.ExcelUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 金华市报名录取专库同步情况表业务实现类
 *
 * @author zhiyuan
 * @since 2024-04-08
 */
@ApiService(funcCode = "syncJhEnroll", title = "金华市报名录取专库同步情况表")
public class EduSyncJhEnrollIntegrationImpl implements EduSyncJhEnrollIntegration {

    @Autowired
    public EduSyncJhEnrollService eduSyncJhEnrollService;

    @Autowired
    private ExcelCommonHelper excelCommonHelper;

    @Autowired
    private RedisHelper redisHelper;

    @Autowired
    private ExcelIntegration excelIntegration;

    @Value("${spring.servlet.multipart.location}")
    private String tempPath;

    @Autowired
    public SysDictService sysDictService;
    @Autowired
    public EduSyncJhApplyService eduSyncJhApplyService;

    @Autowired
    public ExcelParamService excelParamService;

    @Autowired
    public ExcelModelService excelModelService;

    @Autowired
    private DictIntegration dictIntegration;

    @Autowired
    private SysApplicationService applicationService;

    @Autowired
    private EduHelper eduHelper;

    @Autowired
    ExcelUtils excelUtils;

    @Autowired
    DictHelper dictHelper;

    @Autowired
    private EduSyncJhEnrollService enrollService;

    @Autowired
    private EduSyncJhEnrollErrorService enrollErrorService;
    @Autowired
    private EduSyncJhApproveService approveService;

    @Autowired
    private EduSyncJhImportBatchService importBatchService;

    @Autowired
    private EduSyncJhImportBatchIntegration importBatchIntegration;

    @Override
    @OpApi(funcCode = "syncJhEnroll0001", title = "金华市报名录取专库同步情况表分页查询", funcType = FuncTypeEnum.query, checkPrivilege = BoolEnum.FALSE)
    public PageInfo<EduSyncJhEnrollVO> getList(EduSyncJhEnrollQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        Boolean desensitizeFlag = vo.getDesensitizeFlag();
        if (desensitizeFlag == null){
            desensitizeFlag = true;
        }
        String loginAreaCode = SessionUtil.getAreaCode();
        if (StringUtils.isBlank(loginAreaCode)) {
            throw new AppException("登录的账号未配置行政区划，请联系管理员进行处理！");
        }
        QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
        String areaCode = eduHelper.thisAreaCode();
        if (!loginAreaCode.equals(areaCode)) {
            //比对行政区划
            queryWrapper.lambda().eq(EduSyncJhEnroll::getApplyCountyCode, loginAreaCode);
        }
        queryWrapper.lambda()
                .eq(vo.getYear() != null, EduSyncJhEnroll::getYear, vo.getYear())
                .eq(StringUtils.isNotBlank(vo.getSchoolCategory()), EduSyncJhEnroll::getSchoolCategory, vo.getSchoolCategory())
                .eq(StringUtils.isNotBlank(vo.getCardType()), EduSyncJhEnroll::getCardType, vo.getCardType())
                .like(StringUtils.isNotBlank(vo.getName()), EduSyncJhEnroll::getName, vo.getName())
                .eq(StringUtils.isNotBlank(vo.getIdcard()), EduSyncJhEnroll::getIdcard, vo.getIdcard())
                .eq(StringUtils.isNotBlank(vo.getEnrollState()), EduSyncJhEnroll::getEnrollState, vo.getEnrollState())
                .eq(StringUtils.isNotBlank(vo.getEnrollHuman()), EduSyncJhEnroll::getEnrollHuman, vo.getEnrollHuman())
                .eq(StringUtils.isNotBlank(vo.getEnrollSchoolName()), EduSyncJhEnroll::getEnrollSchoolName, vo.getEnrollSchoolName())
                .eq(StringUtils.isNotBlank(vo.getApplyCountyCode()), EduSyncJhEnroll::getApplyCountyCode, vo.getApplyCountyCode())
                .orderByDesc(EduSyncJhEnroll::getUpdateTime, EduSyncJhEnroll::getCreateTime, EduSyncJhEnroll::getName);
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        List<EduSyncJhEnroll> list = eduSyncJhEnrollService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduSyncJhEnroll> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduSyncJhEnrollVO> resultList = Convert.toList(EduSyncJhEnrollVO.class, pageInfo.getList());
        // 转义数据字典值
        dictHelper.valueToName(resultList, Arrays.asList(JhSyncTypeEnum.values()));
        if (desensitizeFlag) {
            for (EduSyncJhEnrollVO enrollVO : resultList) {
                enrollVO.setName(EduDesensitizeUtil.desensitizeFullName(enrollVO.getName()));
                enrollVO.setIdcard(EduDesensitizeUtil.desensitizeIdcard(enrollVO.getIdcard()));
            }
        }
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "syncJhEnroll0002", title = "金华市报名录取专库同步情况表根据主键查询详情", funcType = FuncTypeEnum.query, checkPrivilege = BoolEnum.FALSE)
    public EduSyncJhEnrollVO getById(EduSyncJhEnrollKeyVO vo) {
        EduSyncJhEnroll entity = eduSyncJhEnrollService.getById(vo.getJhEnrollId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduSyncJhEnrollVO result = Convert.convert(EduSyncJhEnrollVO.class, entity);
        return result;
    }

    /**
     * 保存前统一校验
     */
    @Override
    @OpApi(funcCode = "syncJhEnroll0003", title = "金华市报名录取专库同步情况表保存前校验", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduSyncJhEnrollVO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验

        if (vo.getYear() == null) {
            vo.setYear(eduHelper.thisYear());
        }
        if (StringUtils.isBlank(vo.getSchoolCategory())) {
            throw new AppException("学段不能为空！");
        }
        if (StringUtils.isBlank(vo.getCardType())) {
            throw new AppException("证件类型不能为空！");
        }
        if (StringUtils.isBlank(vo.getName())) {
            throw new AppException("姓名不能为空！");
        }
        if (StringUtils.isBlank(vo.getIdcard())) {
            throw new AppException("证件号码不能为空！");
        }
        if (StringUtils.isBlank(vo.getEnrollState())) {
            throw new AppException("录取状态不能为空！");
        }
        if (StringUtils.isBlank(vo.getEnrollHuman())) {
            throw new AppException("录取人不能为空！");
        }
        if (ObjectUtils.isEmpty(vo.getEnrollTime())) {
            throw new AppException("录取时间不能为空！");
        }
        if (StringUtils.isBlank(vo.getEnrollSchoolName())) {
            throw new AppException("录取学校不能为空！");
        }
        if (StringUtils.isBlank(vo.getApplyCountyCode())) {
            throw new AppException("报名所在区县码不能为空！");
        }
        if (vo.getCardType().equalsIgnoreCase(CardTypeEnum.idcard.getType())) {
            if (!IdcardUtil.isValidCard(vo.getIdcard())) {
                throw new AppException("身份证格式有误！");
            }
        }
        //校验录取状态是否符合要求
        if (!vo.getEnrollState().equalsIgnoreCase("1")
                && !vo.getEnrollState().equalsIgnoreCase("2")) {
            throw new AppException("录取状态只能为1或2 1代表录取  2代表不录取！");
        }

        //判断学段是否符合要求
        if (  !vo.getSchoolCategory().equalsIgnoreCase("2")
                && !vo.getSchoolCategory().equalsIgnoreCase("3")) {
            throw new AppException("学段只能为数字2或3，2代表小学，3代表初中！");
        }

        //校验证件类型是否符合要求
        if (!vo.getCardType().equalsIgnoreCase("01")
                && !vo.getCardType().equalsIgnoreCase("02")
                && !vo.getCardType().equalsIgnoreCase("03")
                && !vo.getCardType().equalsIgnoreCase("04")
                && !vo.getCardType().equalsIgnoreCase("05")
                && !vo.getCardType().equalsIgnoreCase("06")
                && !vo.getCardType().equalsIgnoreCase("99")) {
            throw new AppException("证件类型只能为数字01或02或03或04或05或06或99，01代表身份证，02代表护照，03代表台胞证，04代表台湾居民来往大陆通行证，05代表港澳居民往来内地通行证，06代表外国人永久居留身份证，99代表其他证件");
        }

        //校验区县码是否为数字
        if (!StringUtils.isNumeric(vo.getApplyCountyCode())) {
            throw new AppException("报名所在区县码只能为数字");
        }
    }

    @Override
    @OpApi(funcCode = "syncJhEnroll0004", title = "金华市报名录取专库同步情况表新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "syncJhEnroll0004",
            operationName = "金华市报名录取专库同步情况表新增",
            dataType = "jhEnrollId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSyncJhEnrollVO add(EduSyncJhEnrollVO vo) {
        //保存前校验
        checkSave(vo);
        //判断报名数据是否存在
        EduSyncJhApply syncJhApply = checkApplyData(vo);
        if (syncJhApply == null) {
            throw new AppException("同步报名数据不存在，请先添加同步报名数据!");
        }

        EduSyncJhApprove syncJhApprove = checkApproveData(vo);
        if (syncJhApprove == null) {
            throw new AppException("同步审核数据不存在，请先添加同步审核数据!");
        }
        vo.setJhApplyId(syncJhApply.getJhApplyId());
        //判断已录取数据是否存在
        QueryWrapper<EduSyncJhEnroll> queryEnrollWrapper = new QueryWrapper<>();
        queryEnrollWrapper.lambda()
                .eq(EduSyncJhEnroll::getYear, vo.getYear())
                .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard())
                .eq(EduSyncJhEnroll::getEnrollState, "1");
        if (eduSyncJhEnrollService.count(queryEnrollWrapper) > 0) {
            throw new AppException("该学生本年度已存在已录取数据！");
        }

        //判断本区域录取数据是否存在
        QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(EduSyncJhEnroll::getYear, vo.getYear())
                .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard())
                .eq(EduSyncJhEnroll::getApplyCountyCode, vo.getApplyCountyCode());
        if (eduSyncJhEnrollService.count(queryWrapper) > 0) {
            throw new AppException("该学生报名区域已存在录取数据！");
        }

        //保存数据
        EduSyncJhEnroll entity = Convert.convert(EduSyncJhEnroll.class, vo);
        eduSyncJhEnrollService.save(entity);
        if (entity.getJhApplyId() == null) {
            throw new AppException("报名同步数据id 不存在，无法进行数据添加，数据有误");
        }
        //将主键设置回vo使操作日志可以取到
        vo.setJhEnrollId(entity.getJhEnrollId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "syncJhEnroll0005", title = "金华市报名录取专库同步情况表修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "syncJhEnroll0005",
            operationName = "金华市报名录取专库同步情况表修改",
            dataType = "jhEnrollId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSyncJhEnrollVO edit(EduSyncJhEnrollVO vo) {
        if (ObjectUtils.isEmpty(vo.getJhEnrollId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduSyncJhEnroll oldEntity = eduSyncJhEnrollService.getById(vo.getJhEnrollId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);

        //判断已录取数据是否存在
        QueryWrapper<EduSyncJhEnroll> queryEnrollWrapper = new QueryWrapper<>();
        queryEnrollWrapper.lambda()
                .eq(EduSyncJhEnroll::getYear, vo.getYear())
                .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard())
                .eq(EduSyncJhEnroll::getEnrollState, "1");
        if (eduSyncJhEnrollService.count(queryEnrollWrapper) > 1) {
            throw new AppException("该学生本年度已存在已录取数据！");
        }

        //判断本区域录取数据是否存在
        QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(EduSyncJhEnroll::getYear, vo.getYear())
                .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard())
                .ne(EduSyncJhEnroll::getJhEnrollId, oldEntity.getJhEnrollId())
                .eq(EduSyncJhEnroll::getApplyCountyCode, vo.getApplyCountyCode());
        if (eduSyncJhEnrollService.count(queryWrapper) >= 1) {
            throw new AppException("该学生报名区域已存在录取数据！");
        }
        //保存数据
        EduSyncJhEnroll entity = Convert.convert(EduSyncJhEnroll.class, vo);
        if (entity.getJhApplyId() == null) {
            throw new AppException("报名同步数据id 不存在，无法进行数据修改，数据有误");
        }
        eduSyncJhEnrollService.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "syncJhEnroll0006", title = "金华市报名录取专库同步情况表根据主键删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "syncJhEnroll0006",
            operationName = "金华市报名录取专库同步情况表删除",
            dataType = "jhEnrollId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduSyncJhEnrollKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getJhEnrollId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduSyncJhEnroll entity = eduSyncJhEnrollService.getById(vo.getJhEnrollId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduSyncJhEnrollService.removeById(vo.getJhEnrollId());
    }

    @Override
    @OpApi(funcCode = "syncJhEnroll0007", title = "金华市报名录取专库同步情况-excel导出",
            funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void exportJhEnrollInfo(EduSyncJhEnrollQueryVO vo, HttpServletResponse response) {
        if (ObjectUtils.isEmpty(vo.getModelCode())) {
            throw new AppException("请传入模板编码!  ");
        }
        ExcelVO excelVO = new ExcelVO();
        excelVO.setModelCode(vo.getModelCode());
        Map<String, List<SelectVO>> dictMap = new HashMap<>();
        //设置学段
        dictMap.put("schoolCategory", importBatchIntegration.getSchoolCategory());
        //设置身份证类型下拉框信息
        dictMap.put("cardType", importBatchIntegration.getCardTypeDict());
        //获取录取状态
        dictMap.put("enrollState", importBatchIntegration.getEnrollStateDict());
        excelVO.setDictMap(dictMap);
        ExcelModelVO excelModelVO = excelIntegration.getModel(excelVO);
        List<ExcelParamVO> paramVOList = excelModelVO.getParamVOList();
        paramVOList = paramVOList.stream().filter(item -> {
            return !"remarks".equals(item.getKey());
        }).collect(Collectors.toList());
        excelModelVO.setParamVOList(paramVOList);
        String destFilePath = this.tempPath + "/" + IdUtil.fastSimpleUUID() + "." + excelModelVO.getExcelType();
        int pageNum = 1;
        //如果数据为空，就下载模板给他
        if (queryCountByVO(vo) == 0) {
            excelCommonHelper.downloadModel(excelModelVO, null, response);
            return;
        }
        setData(excelModelVO, null, destFilePath, vo, pageNum);
        String fileName = "金华市录取同步数据" + DateUtil.today();
        if (StringUtils.isBlank(fileName)) {
            fileName =
                    excelModelVO.getModelName()
                            + "_"
                            + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN)
                            + "."
                            + (StringUtils.isBlank(excelModelVO.getExcelType())
                            ? "xls"
                            : excelModelVO.getExcelType());
        }
        File file = FileUtil.file(destFilePath);
        BufferedInputStream in = null;
        try {
            in = FileUtil.getInputStream(file);
            ServletUtil.write(response, in, "application/octet-stream;charset=utf-8", fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            FileUtil.del(destFilePath);
        }
    }


    @Override
    @OpApi(funcCode = "syncJhEnroll0008", title = "金华市报名录取专库同步情况-excel导入并保存",
            funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void inputJhEnrollInfo(ExcelVO vo, MultipartFile file) {
        ExcelModelVO excelModelVO = excelUtils.getModel(vo);
        InputStream in = null;
        try {
            String areaCode = SessionUtil.getAreaCode();
            if (StringUtils.isBlank(areaCode)){
                throw new AppException("该账号未配置统筹区划，请先联系管理人员进行配置！");
            }
            // 根据行政区划来加锁
            String redisKey= EduCache.EdU_SYNC_JH_Enroll_LOCK+areaCode;
            boolean lock = false;
            lock = redisHelper.hasKey(redisKey);
            if (lock) {
                throw new AppException("录取专库同步正在同步中，请稍后再试！");
            }else{
                //获取不到，就设置锁
                redisHelper.set(redisKey, true, 7200);
            }
            try {
                in = file.getInputStream();
                //记录已经导入的证件信息
                List<String> idcardList = new ArrayList<>();
                List<Map<String, Object>> list = excelCommonHelper.readExcel(excelModelVO, in, true);
                if (CollectionUtils.isEmpty(list)) {
                    throw new AppException("导入的excel文档数据为空，请填写数据后重试!");
                }
                //插入成功得到批次id
                Long importBatchId = importBatchService.createImportBatch(JhSyncImportEnum.enroll);
                for (Map<String, Object> map : list) {
                    //将读取的json对象转换为VO
                    EduSyncJhEnrollVO enrollVO = JSON.parseObject(JSON.toJSONString(map), EduSyncJhEnrollVO.class);
                    //校验数据，如果有错误，拼接到remarks中
                    String remarks = "";
                    Boolean checkFlag = importCheck(enrollVO,remarks,idcardList);
                    if (!checkFlag){
                        EduSyncJhEnrollError enrollError = Convert.convert(EduSyncJhEnrollError.class, enrollVO);
                        enrollError.setAreaCode(SessionUtil.getAreaCode());
                        enrollError.setImportBatchId(importBatchId);
                        enrollErrorService.save(enrollError);
                        continue;
                    }

                    QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda()
                            .select(EduSyncJhEnroll::getJhEnrollId)
                            .eq(EduSyncJhEnroll::getIdcard, enrollVO.getIdcard())
                            .eq(EduSyncJhEnroll::getYear, enrollVO.getYear());
                    EduSyncJhEnroll syncJhEnroll = enrollService.getOne(queryWrapper, false);
                    if (!ObjectUtils.isEmpty(syncJhEnroll)) {
                        enrollVO.setJhEnrollId(syncJhEnroll.getJhEnrollId());
                    }
                    EduSyncJhEnroll saveEnroll = Convert.convert(EduSyncJhEnroll.class, enrollVO);
                    enrollService.saveOrUpdate(saveEnroll);
                }
            }finally {
                // 释放锁
                redisHelper.del(redisKey);
            }
        }catch (AppException appEx) {
            throw appEx;
        } catch (IOException e) {
            throw new AppException("读取文件异常:" + e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    @OpApi(funcCode = "syncJhEnroll0009", title = "录取同步模板下载（PC）",
            funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void downloadModel(ExcelVO excelVO, HttpServletResponse response) {
        //填写下拉框数据
        Map<String, List<SelectVO>> dictMap = new HashMap<>();
        //设置学段
        dictMap.put("schoolCategory", importBatchIntegration.getSchoolCategory());
        //设置身份证类型下拉框信息
        dictMap.put("cardType", importBatchIntegration.getCardTypeDict());
        //获取录取状态
        dictMap.put("enrollState", importBatchIntegration.getEnrollStateDict());
        excelVO.setDictMap(dictMap);
        ExcelModelVO excelModelVO=excelIntegration.getModel(excelVO);
        List<ExcelParamVO> paramVOList = excelModelVO.getParamVOList();
        List<String> removeParams = new ArrayList<>();
        removeParams.add("remarks");
        removeParams.add("applyCountyName");
        paramVOList = paramVOList.stream().filter(item ->{
            return !removeParams.contains(item.getKey());
        }).collect(Collectors.toList());
        excelModelVO.setParamVOList(paramVOList);
        excelCommonHelper.downloadModel(excelModelVO,excelVO.getRows(),response);
    }

    @Override
    public void syncDelete(EduSyncJhDeleteQueryVO vo) {
        QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(EduSyncJhEnroll::getYear, vo.getYear())
                .eq(EduSyncJhEnroll::getApplyCountyCode, vo.getApplyCountyCode())
                .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard());
        EduSyncJhEnroll syncJhEnroll = eduSyncJhEnrollService.getOne(queryWrapper, false);
        if (ObjectUtils.isEmpty(syncJhEnroll)) {
           return;
        }
        eduSyncJhEnrollService.removeById(syncJhEnroll.getJhEnrollId());
    }

    @Override
    @Transactional
    @OpApi(funcCode = "syncSaveJhEnroll0001", title = "金华市学生录取信息同步-向外暴露接口",
            funcType = FuncTypeEnum.insert, checkPrivilege = BoolEnum.FALSE,savelog = true)
    public EduSyncJhEnrollVO saveSyncEnrollInfo(EduSyncJhEnrollVO vo, HttpServletRequest request) {
        String appId = request.getHeader("appId");
        if (StringUtils.isBlank(appId)){
            throw new AppException("应用id不能为空！");
        }
        //保存前校验
        checkSave(vo);
        DictQueryVO areaDictQueryVO = new DictQueryVO();
        areaDictQueryVO.setDictField("AREA");
        areaDictQueryVO.setDictKey(vo.getApplyCountyCode());
        String areaName = dictIntegration.getValue(areaDictQueryVO);
        if (StringUtils.isBlank(areaName)){
            throw new AppException("传入的区县编码不正确，请根据提供的接口文档规范上传！");
        }
        vo.setApplyCountyName(areaName);

        //校验行政区划和当前配置的应用id 是否一样
        SysApplication sysApplication = applicationService.getById(appId);
        //根据，来分割remarks
        String remarks = sysApplication.getRemarks();
        if (StringUtils.isEmpty(remarks)){
            throw new AppException("应用id未配置行政区划，请联系管理员进行配置！");
        }
        List areaList = Arrays.asList(remarks.split(","));
        if (!areaList.contains(vo.getApplyCountyCode())){
            throw new AppException("传入的区县编码和申请的应用区县编码不一致，应用区县编码 ["+remarks+"]请根据提供的接口文档规范上传！");
        }

        //判断报名数据是否存在
        EduSyncJhApply syncJhApply = checkApplyData(vo);
        if (syncJhApply == null) {
            throw new AppException("同步报名数据不存在，请先添加同步报名数据!");
        }

        EduSyncJhApprove syncJhApprove = checkApproveData(vo);
        if (syncJhApprove == null) {
            throw new AppException("同步审核数据不存在，请先添加同步审核数据!");
        }
        vo.setJhApplyId(syncJhApply.getJhApplyId());
        //保存数据
        EduSyncJhEnroll entity = Convert.convert(EduSyncJhEnroll.class, vo);
        //判断已录取数据是否存在
        QueryWrapper<EduSyncJhEnroll> queryEnrollWrapper = new QueryWrapper<>();
        queryEnrollWrapper.lambda()
                .eq(EduSyncJhEnroll::getYear, vo.getYear())
                .eq(EduSyncJhEnroll::getEnrollState,"1")
                .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard());
        if (eduSyncJhEnrollService.count(queryEnrollWrapper) > 0) {
            EduSyncJhEnroll syncJhEnroll = eduSyncJhEnrollService.getOne(queryEnrollWrapper, false);
            if (!areaList.contains(syncJhEnroll.getApplyCountyCode())){
                throw new AppException("该学生以被"+syncJhEnroll.getApplyCountyName()+"教育局同步录取，无法进行同步上传！");
            }else{
                entity.setJhEnrollId(syncJhEnroll.getJhEnrollId());
            }
        }else{
            //判断报名区域是否有录取数据
            QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(EduSyncJhEnroll::getYear, vo.getYear())
                    .eq(EduSyncJhEnroll::getApplyCountyCode, vo.getApplyCountyCode())
                    .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard());
            if (eduSyncJhEnrollService.count(queryWrapper) > 0) {
                EduSyncJhEnroll syncJhEnroll = eduSyncJhEnrollService.getOne(queryWrapper, false);
                entity.setJhEnrollId(syncJhEnroll.getJhEnrollId());
            }
        }

        if (entity.getJhApplyId() == null) {
            throw new AppException("报名同步数据id 不存在，无法进行数据添加，数据有误");
        }
        eduSyncJhEnrollService.saveOrUpdate(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setJhEnrollId(entity.getJhEnrollId());
        return vo;
    }

    @Override
    @Transactional
    @OpApi(funcCode = "syncSaveJhEnroll0002", title = "金华市学生录取信息同步-内部接口",
            funcType = FuncTypeEnum.insert, checkPrivilege = BoolEnum.FALSE)
    public EduSyncJhEnrollVO saveSyncEnrollInfo2(EduSyncJhEnrollVO vo) {
        //保存前校验
        checkSave(vo);
        DictQueryVO areaDictQueryVO = new DictQueryVO();
        areaDictQueryVO.setDictField("AREA");
        areaDictQueryVO.setDictKey(vo.getApplyCountyCode());
        String areaName = dictIntegration.getValue(areaDictQueryVO);
        if (StringUtils.isBlank(areaName)){
            throw new AppException("传入的区县编码不正确，请根据提供的接口文档规范上传！");
        }
        vo.setApplyCountyName(areaName);

        //判断报名数据是否存在
        EduSyncJhApply syncJhApply = checkApplyData(vo);
        if (syncJhApply == null) {
            throw new AppException("同步报名数据不存在，请先添加同步报名数据!");
        }

        EduSyncJhApprove syncJhApprove = checkApproveData(vo);
        if (syncJhApprove == null) {
            throw new AppException("同步审核数据不存在，请先添加同步审核数据!");
        }
        vo.setJhApplyId(syncJhApply.getJhApplyId());
        //保存数据
        EduSyncJhEnroll entity = Convert.convert(EduSyncJhEnroll.class, vo);
        //判断录取数据是否存在
        QueryWrapper<EduSyncJhEnroll> queryEnrollWrapper = new QueryWrapper<>();
        queryEnrollWrapper.lambda()
                .eq(EduSyncJhEnroll::getYear, vo.getYear())
                .eq(EduSyncJhEnroll::getEnrollState,"1")
                .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard());
        EduSyncJhEnroll syncJhEnroll = eduSyncJhEnrollService.getOne(queryEnrollWrapper, false);
        if (!ObjectUtils.isEmpty(syncJhEnroll)) {
            //判断获取的数据和传来的行政区划是否一致
            if (!syncJhEnroll.getApplyCountyCode().equals(vo.getApplyCountyCode())) {
                throw new AppException("该学生以被"+syncJhEnroll.getApplyCountyName()+"教育局录取，无法进行同步上传！");
            }else{
                entity.setJhEnrollId(syncJhEnroll.getJhEnrollId());
            }
        }else{
            //判断报名区域是否有录取数据
            QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(EduSyncJhEnroll::getYear, vo.getYear())
                    .eq(EduSyncJhEnroll::getApplyCountyCode, vo.getApplyCountyCode())
                    .eq(EduSyncJhEnroll::getIdcard, vo.getIdcard());
            if (eduSyncJhEnrollService.count(queryWrapper) > 0) {
                EduSyncJhEnroll jhEnroll = eduSyncJhEnrollService.getOne(queryWrapper, false);
                entity.setJhEnrollId(jhEnroll.getJhEnrollId());
            }
        }
        if (entity.getJhApplyId() == null) {
            throw new AppException("报名同步数据id 不存在，无法进行数据添加，数据有误");
        }
        eduSyncJhEnrollService.saveOrUpdate(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setJhEnrollId(entity.getJhEnrollId());
        return vo;
    }

    /**
     * 根据年度和身份证信息返回报名同步数据
     *
     * @param vo
     * @return
     */
    private EduSyncJhApply checkApplyData(EduSyncJhEnrollVO vo) {
        QueryWrapper<EduSyncJhApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduSyncJhApply::getYear, vo.getYear())
                .eq(EduSyncJhApply::getApplyCountyCode, vo.getApplyCountyCode())
                .eq(EduSyncJhApply::getIdcard, vo.getIdcard());
        EduSyncJhApply syncJhApply = eduSyncJhApplyService.getOne(queryWrapper, false);
        return syncJhApply;
    }


    /**
     * 获取审核数据
     *
     * @param vo
     * @return
     */
    private EduSyncJhApprove checkApproveData(EduSyncJhEnrollVO vo) {
        if (vo.getYear() == null) {
            throw new AppException("年份不能为空!");
        }
        QueryWrapper<EduSyncJhApprove> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(EduSyncJhApprove::getYear, vo.getYear())
                .eq(EduSyncJhApprove::getApplyCountyCode, vo.getApplyCountyCode())
                .eq(EduSyncJhApprove::getIdcard, vo.getIdcard());
        EduSyncJhApprove approve = approveService.getOne(queryWrapper, false);
        return approve;
    }

    private int queryCountByVO(EduSyncJhEnrollQueryVO vo) {
        String loginAreaCode = SessionUtil.getAreaCode();
        if (StringUtils.isBlank(loginAreaCode)) {
            throw new AppException("登录的账号未配置行政区划，请联系管理员进行处理！");
        }
        QueryWrapper<EduSyncJhEnroll> queryWrapper = new QueryWrapper<>();
        String areaCode = eduHelper.thisAreaCode();
        if (!loginAreaCode.equals(areaCode)) {
            //比对行政区划
            queryWrapper.lambda().eq(EduSyncJhEnroll::getApplyCountyCode, loginAreaCode);
        }
        queryWrapper.lambda()
                .eq(vo.getYear() != null, EduSyncJhEnroll::getYear, vo.getYear())
                .eq(StringUtils.isNotBlank(vo.getSchoolCategory()), EduSyncJhEnroll::getSchoolCategory, vo.getSchoolCategory())
                .eq(StringUtils.isNotBlank(vo.getCardType()), EduSyncJhEnroll::getCardType, vo.getCardType())
                .like(StringUtils.isNotBlank(vo.getName()), EduSyncJhEnroll::getName, vo.getName())
                .eq(StringUtils.isNotBlank(vo.getIdcard()), EduSyncJhEnroll::getIdcard, vo.getIdcard())
                .eq(StringUtils.isNotBlank(vo.getEnrollState()), EduSyncJhEnroll::getEnrollState, vo.getEnrollState())
                .eq(StringUtils.isNotBlank(vo.getEnrollHuman()), EduSyncJhEnroll::getEnrollHuman, vo.getEnrollHuman())
                .eq(StringUtils.isNotBlank(vo.getEnrollSchoolName()), EduSyncJhEnroll::getEnrollSchoolName, vo.getEnrollSchoolName())
                .eq(StringUtils.isNotBlank(vo.getApplyCountyCode()), EduSyncJhEnroll::getApplyCountyCode, vo.getApplyCountyCode());
        return (int) eduSyncJhEnrollService.count(queryWrapper);
    }


    private void setData(ExcelModelVO excelModelVO, ExcelWriter excelWriter, String destFilePath, EduSyncJhEnrollQueryVO vo, int pageNum) {
        vo.setPageNum(pageNum);
        vo.setPageSize(500);
        boolean closeFlag = false;
        try {
            PageInfo<EduSyncJhEnrollVO> pageInfo = getList(vo);
            String total = String.valueOf(pageInfo.getTotal());
            List<Map<String, Object>> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(pageInfo.getList())) {
                for (EduSyncJhEnrollVO enrollVO : pageInfo.getList()) {
                    //将数据字典的key 转换为value
                    dictKeyToValue(enrollVO);
                    list.add(BeanUtil.beanToMap(enrollVO, false, true));
                }
            }
            if (pageNum == 1) {
                if (excelWriter == null) {
                    excelWriter = excelCommonHelper.createExcelWriter(excelModelVO, destFilePath, Integer.parseInt(total));
                }
                excelCommonHelper.writeMap(excelWriter, list);
            } else {
                excelCommonHelper.writeMap(excelWriter, list);
            }
            if (pageInfo.isHasNextPage()) {
                pageNum = pageNum + 1;
                setData(excelModelVO, excelWriter, destFilePath, vo, pageNum);
            } else {
                closeFlag = true;
            }
        } catch (AppException appEx) {
            throw appEx;
        } catch (Exception e) {
            throw new AppException("调用自定义写入服务异常:" + e.getMessage());
        } finally {
            if (closeFlag && excelWriter != null) {
                excelWriter.close();
            }
        }
    }

    private void dictKeyToValue(EduSyncJhEnrollVO enrollVO) {
        //转换学段
        if (StringUtils.isNotBlank(enrollVO.getSchoolCategory())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("SCHOOLCATEGORY");
            dictQueryVO.setDictKey(enrollVO.getSchoolCategory());
            String schoolCategory = dictIntegration.getValue(dictQueryVO);
            enrollVO.setSchoolCategory(schoolCategory);
        }

        //转换证件类型
        if (StringUtils.isNotBlank(enrollVO.getCardType())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("CARDTYPE");
            dictQueryVO.setDictKey(enrollVO.getCardType());
            String cardType = dictIntegration.getValue(dictQueryVO);
            enrollVO.setCardType(cardType);
        }

        //转换审核状态
        if (StringUtils.isNotBlank(enrollVO.getEnrollState())) {
            DictQueryVO dictQueryVO = new DictQueryVO();
            dictQueryVO.setDictField("ENROLLSTATE");
            dictQueryVO.setDictKey(enrollVO.getEnrollState());
            String enrollState = dictIntegration.getValue(dictQueryVO);
            enrollVO.setEnrollState(enrollState);
        }
    }


    /**
     * 导入校验
     * @param enrollVO
     * @param remarks
     * @param idcardList
     * @return
     */
    private Boolean importCheck(EduSyncJhEnrollVO enrollVO, String remarks, List<String> idcardList) {
        if (enrollVO.getYear() == null) {
            enrollVO.setYear(eduHelper.thisYear());
        }
        boolean flag = true;
        if (StringUtils.isBlank(enrollVO.getIdcard())){
            remarks = "证件号码不能为空";
            flag = false;
        } else{
            String cardType = enrollVO.getCardType().trim();
            if (Validator.isChinese(cardType)) {
                //如果为中文 根据数据字典的value  得到key 值
                DictQueryVO dictQueryVO = new DictQueryVO();
                dictQueryVO.setDictField("CARDTYPE");
                dictQueryVO.setDictValue(cardType);
                String key = dictIntegration.getKey(dictQueryVO);
                if (StringUtils.isBlank(key)) {
                    remarks += "学生证件类型数据格式不对！ 正确格式： 如 身份证/护照/台胞证/台湾居民来往大陆通行证/港澳居民往来内地通行证/外国人永久居留身份证/其他证件!  ";
                    flag = false;
                } else {
                    enrollVO.setCardType(key);
                }
            }else{
                remarks += "学生证件类型数据格式不对！ 正确格式： 如 身份证/护照/台胞证/台湾居民来往大陆通行证/港澳居民往来内地通行证/外国人永久居留身份证/其他证件!  ";
                flag = false;
            }
            enrollVO.setIdcard(enrollVO.getIdcard().trim().toUpperCase());
            //证件类型为数字，判断是否为身份证类型
            if (CardTypeEnum.idcard.getType().equals(enrollVO.getCardType())
                    && !IdcardUtil.isValidCard(enrollVO.getIdcard())) {
                remarks += "学生证件数据格式不对！";
                flag = false;
            }
        }

        //校验学段
        if (StringUtils.isBlank(enrollVO.getSchoolCategory())) {
            remarks += "学生学段不能为空!  ";
            flag = false;
        } else {
            String schoolCategory = enrollVO.getSchoolCategory().trim();
            if (Validator.isChinese(schoolCategory)) {
                DictQueryVO dictQueryVO = new DictQueryVO();
                dictQueryVO.setDictField("SCHOOLCATEGORY");
                dictQueryVO.setDictValue(schoolCategory);
                String key = dictIntegration.getKey(dictQueryVO);
                if (StringUtils.isBlank(key)) {
                    flag = false;
                    remarks += "学生学段数据格式不对！ 正确格式：如 小学/初中! ";
                } else {
                    enrollVO.setSchoolCategory(key);
                }
            } else {
                flag = false;
                remarks += "学生学段数据格式不对！ 正确格式：如 小学/初中! ";
            }
        }

        //校验录取状态
        if (StringUtils.isBlank(enrollVO.getEnrollState())) {
            remarks += "学生录取状态不能为空!  ";
            flag = false;
        } else {
            String enrollState = enrollVO.getEnrollState().trim();
            if (Validator.isChinese(enrollState)) {
                DictQueryVO dictQueryVO = new DictQueryVO();
                dictQueryVO.setDictField("ENROLLSTATE");
                dictQueryVO.setDictValue(enrollState);
                String key = dictIntegration.getKey(dictQueryVO);
                if (StringUtils.isBlank(key)) {
                    flag = false;
                    remarks += "学生录取状态数据格式不对！ 正确格式：如 录取/未录取! ";
                } else {
                    enrollVO.setEnrollState(key);
                }
            }else{
                flag = false;
                remarks += "审核状态数据格式不对！ 正确格式：如 通过/不通过!  ";
            }
        }


        //校验录取所在区县名
        String areaCode = SessionUtil.getAreaCode();
        DictQueryVO dictQueryVO = new DictQueryVO();
        dictQueryVO.setDictField("AREA");
        dictQueryVO.setDictKey(areaCode);
        String areaName = dictIntegration.getValue(dictQueryVO);
        enrollVO.setApplyCountyName(areaName);
        enrollVO.setApplyCountyCode(areaCode);

        //校验身份证是否存在
        if (idcardList.contains(enrollVO.getIdcard())) {
            flag = false;
            remarks += "该身份证已存在，请检查!  ";
        } else {
            idcardList.add(enrollVO.getIdcard());
        }

        //校验录取时间
        if(ObjectUtils.isEmpty(enrollVO.getEnrollTime())){
            flag = false;
            remarks += "录取时间不能为空!  ";
        }

        //校验录取人
        if(StringUtils.isBlank(enrollVO.getEnrollHuman())){
            flag = false;
            remarks += "录取人不能为空!  ";
        }

        //校验录取学校
        if(StringUtils.isBlank(enrollVO.getEnrollSchoolName())){
            flag = false;
            remarks += "录取学校不能为空!  ";
        }

        //校验报名信息是否存在
        EduSyncJhApply syncJhApply = checkApplyData(enrollVO);
        if(syncJhApply == null){
            flag = false;
            remarks += "该学生同步报名信息不存在,请先添加该学生报名信息！ ";
        }else{
            enrollVO.setJhApplyId(syncJhApply.getJhApplyId());
        }

        //校验审核信息是否存在
        EduSyncJhApprove syncJhApprove = checkApproveData(enrollVO);
        if(syncJhApprove == null){
            flag = false;
            remarks += "该学生同步审核信息不存在,请先添加该学生审核信息！ ";
        }
        //设置备注信息
        enrollVO.setRemarks(remarks);

        return flag;
    }

}
